package com.ruoyi.business.rule.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ruoyi.business.base.JoBaseServiceImpl;
import com.ruoyi.business.customer.domain.JbCustomer;
import com.ruoyi.business.customer.service.JbCustomerService;
import com.ruoyi.business.rule.domain.*;
import com.ruoyi.business.rule.mapper.JbRulesMapper;
import com.ruoyi.business.rule.service.JbRulesHistoryService;
import com.ruoyi.business.rule.service.JbRulesService;
import com.ruoyi.business.sundry.domain.JbNotification;
import com.ruoyi.business.sundry.service.JbNotificationService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;

/**
 * 业务规则Service业务层处理
 *
 * @author ruoyi
 * @date 2024-10-11
 */
@Service
@Slf4j
public class JbRulesServiceImpl
        extends JoBaseServiceImpl<JbRulesMapper, JbRules>
        implements JbRulesService
{
    @Autowired
    private JbRulesHistoryService jbRulesHistoryService;
    @Autowired
    private JbCustomerService jbCustomerService;
    @Autowired
    private JbNotificationService jbNotificationService;

    @Override
    public Boolean updateInfoById(JbRules rules)
    {
        JbRules byId = this.getById(rules.getId());
        jbRulesHistoryService.save(new JbRulesHistory(byId));
        recordAutomaticTime(rules, byId);
        this.updateById(rules);
        return true;
    }

    @Override
    @Async
    public void deptHighseas(JbRules jbRules)
    {
        log.info("===========部门公海进入规则未跟进执行-{}", LocalDateTime.now());
        long currentTime = System.currentTimeMillis();
        JbDeptHighseasRulesJson bean = BeanUtil.toBean(jbRules.getExecutionContent(), JbDeptHighseasRulesJson.class);
        JbHighseasContentJson contentJson = bean.getNotFollowUp();
        if (ObjectUtils.isEmpty(contentJson.getStartFlag()) || !Constants.PUBLIC_NUMBER_0.equals(contentJson.getStartFlag()))
        {
            //未跟进配置未启用
            log.info("===未跟进配置未启用.不处理");
            return;
        }
        Integer dayNumber = contentJson.getDay();
        if (ObjectUtils.isEmpty(dayNumber) || dayNumber.intValue() == Constants.PUBLIC_NUMBER_0.intValue())
        {
            log.info("===设置未跟进天数为空或0.不处理");
            return;
        }
        int i = bean.getAutomaticTime().compareTo(contentJson.getAutomaticTime());
        // 取最后一个开启自动时间
        Date startDate = contentJson.getAutomaticTime();
        if (i > 0)
        {
            startDate = bean.getAutomaticTime();
        }
        String defaultDate = "2000-01-01 10:10:10";
        String rulesTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate);
        Integer reminderTime = contentJson.getReminderTime();
        String dayTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date());
        StringJoiner sql = new StringJoiner(" ").add("""
                select ct.id,
                ct.business_manager_id,
                ct.customer_name,
                ct.latestFollowupTime,
                ct.orderTime,
                ct.transferTime\s
                FROM
                	(
                	SELECT
                		jc.id,
                		jc.business_manager_id,
                		jc.customer_name,
                		jc.latest_followup_time latestFollowupTime,
                		( SELECT create_time FROM jb_order jo WHERE jo.customer_id = jc.id and jo.del_flag=0 ORDER BY jo.id DESC LIMIT 1 ) AS orderTime,
                		jc.transfer_customer_time AS transferTime\s
                	FROM
                		jb_customer jc\s
                	WHERE
                		jc.del_flag = '0'\s
                		AND jc.data_type = 0\s
                	AND jc.is_invalid = 0\s
                	) AS ct 
                """);
        //当天时间-最后一个操作时间，得到天数
        sql.add(String.format(" where DATEDIFF('%s',", dayTime));
        //四个时间取最后一个时间,最后跟进时间，订单时间，转移客户时间，规则启动时间
        sql.add(String.format("GREATEST(IFNULL(ct.latestFollowupTime,'%s'),IFNULL(ct.orderTime,'%s'),", defaultDate, defaultDate));
        sql.add(String.format("IFNULL(ct.transferTime,'%s'),'%s'))", defaultDate, rulesTime));
        setTaskUser();
        String content = "";
        if (ObjectUtils.isNotEmpty(reminderTime) && reminderTime.intValue() > 0)
        {
            //前几天提醒
            reminderTime = dayNumber - reminderTime;
            //获取提前一天提醒的数据
            content = sql + "=" + reminderTime;
            List<JbCustomer> jbOpportunities = joSqlUtil.jsonToEntity(baseMapper.findJson(content), JbCustomer.class);
            List<JbNotification> addNotification = Lists.newArrayList();
            jbOpportunities.forEach(a ->
            {
                JbNotification notification = new JbNotification();
                notification.setSenderId(-666L);
                notification.setSenderName("系统");
                notification.setRecipientId(a.getBusinessManagerId());
                notification.setDataType(Constants.PUBLIC_NUMBER_1);
                notification.setTitle(StringUtils.format("您的客户【{}】即将过期，请尽快处理!",a.getCustomerName()));
                notification.setContent(a.getCustomerName());
                notification.setSendTime(new Date());
                notification.setOperModuleId(a.getId().toString());
                addNotification.add(notification);
            });
            log.info("===========部门公海进入规则未跟进提醒-{},", addNotification);
            if (ObjectUtils.isNotEmpty(addNotification))
            {
                boolean b = jbNotificationService.saveBatch(addNotification);
                log.info("===========部门公海进入规则未跟进提醒结束-{},", b);
            }

        }
        content = sql + ">=" + dayNumber;
        List<JbCustomer> jbOpportunities = joSqlUtil.jsonToEntity(baseMapper.findJson(content), JbCustomer.class);
        List<JbCustomer> updateCustomer = Lists.newArrayList();
        jbOpportunities.forEach(a ->
        {
            JbCustomer update = new JbCustomer();
            update.setId(a.getId());
            update.setDataType(Constants.PUBLIC_NUMBER_2);
            update.setDataTypeTime(new Date());
            updateCustomer.add(update);
        });
        log.info("===========部门公海进入规则未跟进修改客户-{},", updateCustomer);
        if (ObjectUtils.isNotEmpty(updateCustomer))
        {
            boolean b = jbCustomerService.updateBatchById(updateCustomer);
            log.info("===========部门公海进入规则未跟进修改客户结束-{},", b);
        }
        log.info("===========部门公海进入规则未跟进执行结束-{},{}", LocalDateTime.now(), System.currentTimeMillis() - currentTime);
    }

    @Override
    @Async
    public void deptHighseasTwo(JbRules jbRules)
    {
        log.info("===========部门公海进入规则未成交执行-{}", LocalDateTime.now());
        long currentTime = System.currentTimeMillis();
        JbDeptHighseasRulesJson bean = BeanUtil.toBean(jbRules.getExecutionContent(), JbDeptHighseasRulesJson.class);
        JbHighseasContentJson contentJson = bean.getNotTrading();
        if (ObjectUtils.isEmpty(contentJson.getStartFlag()) || !Constants.PUBLIC_NUMBER_0.equals(contentJson.getStartFlag()))
        {
            //未跟进配置未启用
            log.info("===未提交配置未启用.不处理");
            return;
        }
        Integer dayNumber = contentJson.getDay();
        if (ObjectUtils.isEmpty(dayNumber) || dayNumber.intValue() == Constants.PUBLIC_NUMBER_0.intValue())
        {
            log.info("===设置未提交天数为空或0.不处理");
            return;
        }
        int i = bean.getAutomaticTime().compareTo(contentJson.getAutomaticTime());
        // 取最后一个开启自动时间
        Date startDate = contentJson.getAutomaticTime();
        if (i > 0)
        {
            startDate = bean.getAutomaticTime();
        }
        String defaultDate = "2000-01-01 10:10:10";
        String rulesTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate);
        Integer reminderTime = contentJson.getReminderTime();
        String dayTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date());
        StringJoiner sql = new StringJoiner(" ").add("""
                SELECT
                	jc.id,
                	jc.business_manager_id,
                	jc.customer_name,
                	jc.latest_followup_time,
                	jc.data_type_time,
                	jc.transfer_customer_time\s
                FROM
                	jb_customer jc\s
                WHERE
                	jc.del_flag = '0'\s
                	AND jc.data_type = 0\s
                	AND jc.is_invalid = 0\s
                	AND NOT EXISTS ( SELECT id FROM jb_order jo WHERE jo.customer_id = jc.id AND jo.del_flag = 0 )\s
                """);
        //客户没有订单数据，且是当天时间-最后一个操作时间，得到天数大于配置时间
        sql.add(String.format(" AND DATEDIFF('%s',", dayTime));
        //四个时间取最后一个时间,转移客户时间，规则启动时间
        sql.add(String.format("GREATEST(IFNULL(jc.transfer_customer_time,'%s'),'%s'))", defaultDate, rulesTime));
        String content = "";
        setTaskUser();
        if (ObjectUtils.isNotEmpty(reminderTime) && reminderTime.intValue() > 0)
        {
            //前几天提醒
            reminderTime = dayNumber - reminderTime;
            //获取提前一天提醒的数据
            content = sql + "=" + reminderTime;
            List<JbCustomer> jbOpportunities = joSqlUtil.jsonToEntity(baseMapper.findJson(content), JbCustomer.class);
            List<JbNotification> addNotification = Lists.newArrayList();
            jbOpportunities.forEach(a ->
            {
                JbNotification notification = new JbNotification();
                notification.setSenderId(0l);
                notification.setSenderName("系统自动处理");
                notification.setRecipientId(a.getBusinessManagerId());
                notification.setDataType(Constants.PUBLIC_NUMBER_1);
                notification.setTitle("客户即将过期通知");
                notification.setContent(a.getId().toString());
                addNotification.add(notification);
            });
            log.info("===========部门公海进入规则未成交提醒-{},", addNotification);
            if (ObjectUtils.isNotEmpty(addNotification))
            {
                boolean b = jbNotificationService.saveBatch(addNotification);
                log.info("===========部门公海进入规则未成交提醒结束-{},", b);
            }

        }
        content = sql + ">=" + dayNumber;
        List<JbCustomer> jbOpportunities = joSqlUtil.jsonToEntity(baseMapper.findJson(content), JbCustomer.class);
        List<JbCustomer> updateCustomer = Lists.newArrayList();
        jbOpportunities.forEach(a ->
        {
            JbCustomer update = new JbCustomer();
            update.setId(a.getId());
            update.setDataType(Constants.PUBLIC_NUMBER_2);
            update.setDataTypeTime(new Date());
            updateCustomer.add(update);
        });
        log.info("===========部门公海进入规则未成交修改客户-{},", updateCustomer);
        if (ObjectUtils.isNotEmpty(updateCustomer))
        {
            boolean b = jbCustomerService.updateBatchById(updateCustomer);
            log.info("===========部门公海进入规则未成交修改客户结束-{},", b);
        }
        log.info("===========部门公海进入规则未成交执行结束-{},{}", LocalDateTime.now(), System.currentTimeMillis() - currentTime);
    }

    @Override
    @Async
    public void companyHighseas(JbRules jbRules)
    {
        log.info("===========公司公海进入规则未成交执行-{}", LocalDateTime.now());
        long currentTime = System.currentTimeMillis();
        JbDeptHighseasRulesJson bean = BeanUtil.toBean(jbRules.getExecutionContent(), JbDeptHighseasRulesJson.class);
        JbHighseasContentJson contentJson = bean.getNotTrading();
        if (ObjectUtils.isEmpty(contentJson.getStartFlag()) || !Constants.PUBLIC_NUMBER_0.equals(contentJson.getStartFlag()))
        {
            //未跟进配置未启用
            log.info("===公司未提交配置未启用.不处理");
            return;
        }
        Integer dayNumber = contentJson.getDay();
        if (ObjectUtils.isEmpty(dayNumber) || dayNumber.intValue() == Constants.PUBLIC_NUMBER_0.intValue())
        {
            log.info("===公司设置未提交天数为空或0.不处理");
            return;
        }
        Integer reminderTime = contentJson.getReminderTime();
        String dayTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date());
        StringJoiner sql = new StringJoiner(" ").add("""
                SELECT
                	jc.id,
                	jc.business_manager_id,
                	jc.customer_name,
                	jc.latest_followup_time,
                	jc.data_type_time,
                	jc.transfer_customer_time\s
                FROM
                	jb_customer jc\s
                WHERE
                	jc.del_flag = '0'\s
                	AND jc.data_type = 2\s
                	AND jc.is_invalid = 0\s
                	AND NOT EXISTS ( SELECT id FROM jb_order jo WHERE jo.customer_id = jc.id AND jo.del_flag = 0 )\s
                """);
        //客户没有订单数据，且是当天时间-进入部门公海的时间，得到天数大于配置时间
        sql.add(String.format(" AND DATEDIFF('%s', jc.data_type_time)", dayTime));
        String content = "";
        setTaskUser();
        if (ObjectUtils.isNotEmpty(reminderTime) && reminderTime.intValue() > 0)
        {
            //前几天提醒
            reminderTime = dayNumber - reminderTime;
            //获取提前一天提醒的数据
            content = sql + "=" + reminderTime;
            List<JbCustomer> jbOpportunities = joSqlUtil.jsonToEntity(baseMapper.findJson(content), JbCustomer.class);
            List<JbNotification> addNotification = Lists.newArrayList();
            jbOpportunities.forEach(a ->
            {
                JbNotification notification = new JbNotification();
                notification.setSenderId(0l);
                notification.setSenderName("系统自动处理");
                notification.setRecipientId(a.getBusinessManagerId());
                notification.setDataType(Constants.PUBLIC_NUMBER_1);
                notification.setTitle("客户即将过期通知");
                notification.setContent(a.getId().toString());
                addNotification.add(notification);
            });
            log.info("===========公司公海进入规则未成交提醒-{},", addNotification);
            if (ObjectUtils.isNotEmpty(addNotification))
            {
                boolean b = jbNotificationService.saveBatch(addNotification);
                log.info("===========公司公海进入规则未成交提醒结束-{},", b);
            }

        }
        content = sql + ">=" + dayNumber;
        List<JbCustomer> jbOpportunities = joSqlUtil.jsonToEntity(baseMapper.findJson(content), JbCustomer.class);
        List<JbCustomer> updateCustomer = Lists.newArrayList();
        jbOpportunities.forEach(a ->
        {
            JbCustomer update = new JbCustomer();
            update.setId(a.getId());
            update.setDataType(Constants.PUBLIC_NUMBER_2);
            update.setDataTypeTime(new Date());
            updateCustomer.add(update);
        });
        log.info("===========公司公海进入规则未成交修改客户-{},", updateCustomer);
        if (ObjectUtils.isNotEmpty(updateCustomer))
        {
            boolean b = jbCustomerService.updateBatchById(updateCustomer);
            log.info("===========公司公海进入规则未成交修改客户结束-{},", b);
        }
        log.info("===========公司公海进入规则未成交执行结束-{},{}", LocalDateTime.now(), System.currentTimeMillis() - currentTime);
    }


    /**
     * 处理定时任务信息 部门公海进入，和公司公海进入使用
     *
     * @param rules
     */
    private void recordAutomaticTime(JbRules rules, JbRules byId)
    {
        JbDeptHighseasRulesJson beanBy = BeanUtil.toBean(byId.getExecutionContent(), JbDeptHighseasRulesJson.class);
        if (Constants.DEPT_HIGHSEAS.equals(byId.getRulesCode()))
        {
            //部门公海进入规则
            Date date = new Date();
            JbDeptHighseasRulesJson bean = BeanUtil.toBean(rules.getExecutionContent(), JbDeptHighseasRulesJson.class);
            bean.setAutomaticTime(beanBy.getAutomaticTime());
            bean.getNotFollowUp().setAutomaticTime(beanBy.getNotFollowUp().getAutomaticTime());
            bean.getNotTrading().setAutomaticTime(beanBy.getNotTrading().getAutomaticTime());
            if (!rules.getExecutionType().equals(byId.getExecutionType()) && rules.getExecutionType().intValue() == Constants.PUBLIC_NUMBER_0.intValue())
            {
                bean.setAutomaticTime(date);
            }
            if (bean.getNotFollowUp().getStartFlag() != beanBy.getNotFollowUp().getStartFlag() && bean.getNotFollowUp().getStartFlag() == Constants.PUBLIC_NUMBER_0)
            {
                bean.getNotFollowUp().setAutomaticTime(date);
            }
            if (bean.getNotTrading().getStartFlag() != beanBy.getNotTrading().getStartFlag() && bean.getNotTrading().getStartFlag() == Constants.PUBLIC_NUMBER_0)
            {
                bean.getNotTrading().setAutomaticTime(date);
            }
            rules.setExecutionContent(JSONObject.from(bean));
        }
        if (Constants.COMPANY_HIGHSEAS.equals(byId.getRulesCode()))
        {
            //公司公海规则进入规则
            JbDeptHighseasRulesJson bean = BeanUtil.toBean(rules.getExecutionContent(), JbDeptHighseasRulesJson.class);
            bean.getNotTrading().setAutomaticTime(beanBy.getNotTrading().getAutomaticTime());
            if (bean.getNotTrading().getStartFlag() != beanBy.getNotTrading().getStartFlag() && bean.getNotTrading().getStartFlag() == Constants.PUBLIC_NUMBER_0)
            {
                bean.getNotTrading().setAutomaticTime(new Date());
            }
            rules.setExecutionContent(JSONObject.from(bean));
        }
    }

    /**
     * 异步处理时使用
     */
    public void setTaskUser()
    {
        SysUser sysUser = new SysUser();
//        sysUser.setUserName(name);
//        sysUser.setNickName(name);
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(-666l);
        loginUser.setUser(sysUser);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
}
